import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
import { nextTick } from "vue";
import { getWeb3 } from "@/utils/getWeb3";
import { getChain } from "@/utils/getChain";
import { chainId } from '@/contract/index'
import { verifyToken, versig, isUserExist } from '@/api'
import { FormatDate } from "@/utils/formatDate";
import { Set_App_Token_Key, Get_App_Token_Key } from "@/utils/auth";

import store from '@/store'

export interface IUserState {
    isRouterAlive: boolean,
}

@Module({ dynamic: true, store, name: 'User' })
class User extends VuexModule implements IUserState {
    public isRouterAlive = true
    public chainId = chainId
    public setWeb3: any
    public setUserAddr: any
    public networkId: any = 0
    public isListening: any
    public UserInfo: any = {}
    public referrerOpen = false

    get web3() {
        return this.setWeb3()
    }

    get userAddr() {
        return this.setUserAddr
    }

    @Mutation
    SET_WEB3(result: { userAddr: any; networkId: number | undefined; isListening: any; web3: any; }) {
        this.setUserAddr = result.userAddr
        this.networkId = result.networkId;
        this.isListening = result.isListening;
        this.setWeb3 = result.web3;
    }

    @Mutation
    SET_referrerOpen(bool: boolean) {
        this.referrerOpen = bool
    }

    @Mutation
    SET_UserInfo(UserInfo: any) {
        this.UserInfo = UserInfo
    }

    @Mutation
    SET_USERADDR(userAddr: string) {
        this.setUserAddr = userAddr
    }

    @Mutation
    SET_ROUTER_ALIVE(isRouterAlive: boolean) {
        this.isRouterAlive = isRouterAlive
    }

    @Action({ rawError: true, commit: "SET_WEB3" })
    public async setRegisterWeb3() {
        return await getWeb3()
    }
    @Action({ rawError: true })
    public async verifyToken(): Promise<any> {
        return new Promise((resolve, reject) => {
            verifyToken().then(async (res) => {
                if (res.data.code == 20) {
                    resolve(res)
                } else {
                    try {
                        const isExist = await isUserExist({ address: UserModule.userAddr })
                        if (isExist.data.code == 20) {
                            const message = "welcome to " + UserModule.userAddr
                            const sign = await UserModule.web3.eth.personal.sign(
                                message,
                                UserModule.userAddr
                            );
                            const res = await versig({
                                message: message,
                                signature: sign,
                            });
                            if (res.data.code == 20) {
                                const key = {
                                    ...Get_App_Token_Key(),
                                    [UserModule.userAddr]: res.data.data.Token,
                                };
                                Set_App_Token_Key(key);
                                resolve(res)
                            } else {
                                reject(res)
                            }
                        } else {
                            reject(res)
                            this.SET_referrerOpen(true)
                        }
                    } catch (error) {
                        reject(error)
                    }
                }
            })
        })
    }

    @Action({ rawError: true })
    public async getRequestAccounts() {
        return new Promise((resolve, reject) => {
            window.ethereum.request({
                method: 'eth_requestAccounts',
            }).then((res: string[]) => {
                if (!this.userAddr) {
                    this.SET_USERADDR(res[0])
                }
                resolve(res[0])
            }).catch((err: any) => {
                if (err.code === 4001) {
                    reject('Please connect to MetaMask.')
                } else {
                    reject(err.message)
                }
            })
        })
    }

    @Action({ rawError: true })
    public async addEthereumChain() {
        return new Promise((resolve, reject) => {
            window.ethereum.request({
                method: 'eth_chainId',
            }).then((res: string) => {
                const toHex: string = this.web3.utils.toHex(this.chainId)
                if (res === toHex) return resolve('ok')
                window.ethereum.request({ method: 'wallet_addEthereumChain', params: getChain(toHex) })
                    .then(() => {
                        resolve('Please connect to MetaMask. node')
                    })
                    .catch((err: any) => {
                        reject(err.message)
                    })
            })
        })
    }

    @Action
    public async loadRequestData() {
        await this.setRegisterWeb3()
        if (this.context.rootState.Erc721) {
            this.context.commit('SET_RESET')
        }
        this.SET_ROUTER_ALIVE(false)
        nextTick(() => {
            this.SET_ROUTER_ALIVE(true)
        });
    }

    @Action
    public async loadPage() {
        this.SET_ROUTER_ALIVE(false)
        nextTick(() => {
            this.SET_ROUTER_ALIVE(true)
        });
    }


    @Action
    public async pollWeb3() {
        if (typeof window.ethereum !== 'undefined') {
            window.ethereum.on("accountsChanged", (accounts: string[]) => {
                this.SET_USERADDR(accounts[0])
                this.SET_ROUTER_ALIVE(false)
                nextTick(() => {
                    this.SET_ROUTER_ALIVE(true)
                })
            });
            window.ethereum.on('chainChanged', () => {
                this.loadRequestData()
            });
        }
    }
}
export const UserModule = getModule(User)


